# Copyright 2010 Giacomo Alzetta
# This file is part of "LimberEditor" and is distribuhited under the
# terms of the MIT license.


import os
import sys
from PyQt4 import QtCore, QtGui
from limber import documentmanager
from limber import componentparser
from limber import abilities


MOCKDIR_PATH = None
_MOCKBASE_DIRECTORY = os.path.join(
                                   os.path.dirname(os.path.realpath(__file__)),
                                   'MockDirs')
LOCAL_MOCKS = None

if not os.path.exists(_MOCKBASE_DIRECTORY):
    sys.sterr.write('Could not find the mock directories.\n')
    sys.stderr.write('This might break some tests.\n')

def get_userdir():
    '''Return the path to the current mock user directory.'''

    if MOCKDIR_PATH is None:
        raise ValueError('MockDirectory not setted!')

    return os.path.join(MOCKDIR_PATH, 'mock-userdir')

def get_systemdir():
    '''Return the path to the current mock system directory.'''

    if MOCKDIR_PATH is None:
        raise ValueError('MockDirectory not setted!')

    return os.path.join(MOCKDIR_PATH, 'mock-systemdir')

def set_mockdir(value, ispath=False):
    '''Sets the mock directory.'''

    global MOCKDIR_PATH
    global LOCAL_MOCKS

    if ispath:
        if not os.path.exists(value):
            raise ValueError('The path to the mock directory does not exist!')

        MOCKDIR_PATH = os.path.realpath(value)
    else:
        path = os.path.join(_MOCKBASE_DIRECTORY, str(value))
        if not os.path.exists(path):
            raise ValueError('The path to the mock directory does not exist!')

        MOCKDIR_PATH = path
    LOCAL_MOCKS = None

def load_local_mocks():
    '''Loads the local mock module.'''

    global LOCAL_MOCKS
    sys.path.insert(0, MOCKDIR_PATH)

    try:
        del sys.modules['local_mocks']
    except KeyError:
        pass

    LOCAL_MOCKS = __import__('local_mocks')
    sys.path.pop(0)

def mock_component_infos(test_num=0):
    '''Return a list of mock infos.'''

    if LOCAL_MOCKS is None:
        load_local_mocks()

    return (componentparser.ComponentInfos(**LOCAL_MOCKS.INFOS[test_num]), )

def mock_components(test_num=0):
    '''Return a list of mock components.'''

    if LOCAL_MOCKS is None:
        load_local_mocks()

    return LOCAL_MOCKS.COMPONENTS[test_num]

def mock_components_and_abilities(test_num=0):
    '''Return a list of tuples of the form: component, abilities.'''

    if LOCAL_MOCKS is None:
        load_local_mocks()

    return LOCAL_MOCKS.COMPONENTS_AND_ABILITIES[test_num]


class MockApplication(QtCore.QObject):

    def __init__(self,parent=None):
        super(MockApplication, self).__init__(parent)

        self.mainwindow = MockMainWindow(self)

    def critical_error(self, *args, **kwargs):
        pass

    def query_save_filename(self, doc):
        return 'path'

    def query_close_document(self, document, message='Close the document?'):
        return documentmanager.SAVE

    def query_discard_document(self, document, message='Discard the document?'):
        return documentmanager.SAVE

    def userdir_path(self):
        return get_userdir()

    def systemdir_path(self):
        return get_systemdir()


class MockViewManager(QtCore.QObject):

    def __init__(self, parent=None):
        super(MockViewManager, self).__init__(parent)

        self._views = []

    def add_view(self, view):
        self._views.append(view)

    def active_view(self):
        try:
            return self._views[-1]
        except IndexError:
            return None

    def remove_view(self, view):
        self._views.remove(view)

    def view_parent(self):
        return self


class MockDocument(QtCore.QObject):

    def __init__(self, parent=None):
        super(MockDocument, self).__init__(parent)

        self._path = None

    def title(self):

        return 'Document title'

    def path(self):
        return self._path

    def set_path(self, path):
        self._path = path

    def save(self):
        pass

    def is_modified(self):
        return True


class MockDocumentWithDirty(MockDocument):
    
    def __init__(self, parent=None):
        super(MockDocumentWithDirty, self).__init__(parent)
        
        self._dirty = True
    
    def is_modified(self):
        
        return self._dirty
    
    def set_modified(self, dirty):
        self._dirty = dirty


class MockView(QtCore.QObject):

    def __init__(self, parent, document):
        super(MockView, self).__init__(parent)

        pass

    def set_title(self, title):

        pass

    def show(self):

        pass


class MockDialogGetter(object):

    def __init__(self):
        self._test_number = 0
        self._dialogs_dict = {}
        self._called_dialogs = []

    def __call__(self, key):
        dlg = self._dialogs_dict[key]
        self._called_dialogs.append(key)
        return dlg

    def set_test(self, num):
        self._test_number = int(num)
        self._update_dialogs()

    def was_called(self, name):
        return name in self._called_dialogs

    def _update_dialogs(self):
        if self._test_number == 0:
            self._dialogs_dict = {
                'query-save-filename' : MockQuerySaveFilenameDlg,
                }
        elif self._test_number == 1:
            self._dialogs_dict = {
                'query-close-document' : MockQueryCloseDocumentDlg,
                }
        elif self._test_number == 2:
            self._dialogs_dict = {
                'query-discard-document' : MockQueryDiscardDocumentDlg,
                }
        elif self._test_number == 3:
            self._dialogs_dict = {
                'query-discard-document' : MockQueryDiscardDocumentDlg2,
                }
        self._called_dialogs = []


mock_get_dialog = MockDialogGetter()


class MockDialogClass(object):
    def __init__(self, parent):
        self._parent = parent
        self._exec_return_val = True

    def show(self):
        pass

    def hide(self):
        pass

    def close(self):
        pass

    def exec_(self):
        return self._exec_return_val


class MockQuerySaveFilenameDlg(MockDialogClass):

    filename = 'save filename'


class MockQueryCloseDocumentDlg(MockDialogClass):

    close_document = True


class MockQueryDiscardDocumentDlg(MockDialogClass):

    discard_document = True


class MockQueryDiscardDocumentDlg2(MockDialogClass):

    discard_document = False


class MockMainWindow(QtCore.QObject):

    def show(self):
        pass


class MockMainWindowGUI(QtGui.QWidget):
    
    application_closure_request = QtCore.pyqtSignal(name='applicationClosureRequest')
    
    create_new_document_request = QtCore.pyqtSignal(name='createNewDocumentRequest')
    close_current_document_request = QtCore.pyqtSignal(name='closeCurrentDocumentRequest')
    
    def __init__(self, parent=None, viewdisplayer=None):
        super(MockMainWindowGUI, self).__init__(parent)
        
        if viewdisplayer is None:
            viewdisplayer = MockDisplayerGUI
            
        self.viewdisplayer = viewdisplayer(self)
    
    def show(self):
        pass


class MockDisplayer(QtCore.QObject):

    def __init__(self, parent):
        super(MockDisplayer, self).__init__(parent)

        self._views = []

    def add_view(self, view):
        self._views.append(view)

    def close_view(self, view):
        self._views.remove(view)

    def has_view(self, view):
        return view in self._views


class MockDisplayerGUI(QtGui.QWidget):
    
    def __init__(self, parent):
        super(MockDisplayerGUI, self).__init__(parent)
        
        self._views = []
    
    def add_view(self, view):
        self._views.append(view)
    
    def close_view(self, view):
        self._views.remove(view)
    
    def has_view(self, view):
        return view in self._views


class MockSignal(object):
    
    def __init__(self, string):
        self._string = str(string)
    
    def __str__(self):
        return self._string
    
    def connect(self, other):
        pass
    
    def emit(self, *args):
        pass
    
    def disconnect(self, other):
        pass


class MockGenericObject(object):
    
    def __init__(self, **kwargs):
        for key, val in kwargs.iteritems():
            setattr(self, key, val)
